home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-1.iso / Files / Tele / Pete Johnson / AreaTrix 1.0.4<source>.sit / AreaTrix.p < prev    next >
Encoding:
Text File  |  1992-11-08  |  51.6 KB  |  1,415 lines  |  [TEXT/PJMM]

  1. program AreaTrix;
  2.  
  3. {    Written by Pete Johnson                                                                                            }
  4. {    Version 1.04 of 6/10/90                                                                                            }
  5. {                                                                                                                            }
  6. {    11/18/89    WaitNextEvent added for MF compatibility                                                        }
  7. {    2/8/90    fixed date anomaly for Tabby log                                                                    }
  8. {    2/28/90    fixed date error which last bug fix introduced                                                }
  9. {    3/1/90    changed To: name from 'Sysop' to actual name                                                    }
  10. {    3/4/90    modified for Mansion compatibility                                                                }
  11. {    3/17/90    v. 2.1    added point compatibility and file forwarding to points                        }
  12. {    3/18/90    v. 2.3    now sorts point and areas files by area, added configurable                    }
  13. {                            file forward name, fixed many bugs.                                                    }
  14. {    3/20/90    v. 2.4    checks password for file forward (and changed syntax of forward request    }
  15. {                            to Password > NodeID)                                                                    }
  16. {    3/22/90    v. 2.41    writes message confirming files have been forwarded                            }
  17. {    3/25/90    v. 2.42    better messages re: file forwarding                                                    }
  18. {    3/26/90    v. 0.90    renamed to AreaTrix, delete files which have been forwarded                    }
  19. {    3/27/90    v. 0.91    added help file response to ? in subject line, shortened                        }
  20. {                            'Response' to 'Reply' in answer message subject                                    }
  21. {    3/28/90    v. 0.92    fixed error in format of PointGroups file                                            }
  22. {    3/30/90    v. 1.0    changed version number for release                                                    }
  23. {    4/16/90    v. 1.01    fixed bug which froze program if :Tabby:AreaTrix Workfile didn't exist    }
  24. {    4/22/90    v. 1.02    added option to not delete forwarded files                                        }
  25. {    4/29/90    v. 1.03    delete feed only if '-' is first character of line                                }
  26. {    5/10/90    v. 1.04    if line in areas.bbs or pointgroups file doesn't have at least one tab,    }
  27. {                            it is ignored. Previously this would cause file corruption.                    }
  28. {    6/10/90    priv        fixed areas.bbs sort so that Unknown is always last an pass-thrus are    }
  29. {                            just prior to Unknown, in alphabetical order.                                    }
  30. {                                                                                                                            }
  31.  
  32. uses
  33.     Globals, HelloTabby, NewFileUtils, ConfigDialog, PurgeFiles, PreScan, MiscUtils;
  34.  
  35. const
  36.     debug = false;        {enable when testing weird new code}
  37.  
  38. var
  39.     AreafixRef, GenericRef, TLogRef, MessageCount: integer;
  40.     Request, SendList, SendAreas, ListForwards: boolean;
  41.     GenericPath, OptionStr, PointNetString: STR255;
  42.     TempString, TheVers, FromName: STR255;
  43.     ForwardName, CapsFwdName, FREQName, CapsFREQName, AgentName, CapsAgentName: STR255;
  44.     GenericEOF: longint;
  45.     MsgToSysopStrHdl: StringHandle;
  46.     MsgToSysop, ListOK, GoodPassword, TabbyLog, FixPending, FromPoint, SendHelp, ListFREQs: boolean;
  47.     DialogPointer: DialogPtr;
  48.  
  49. { ------------------------------------------------------ }
  50.  
  51. procedure ParseReq;
  52.  
  53.     type
  54.         Area = record
  55.                 AreaNum: string[3];
  56.                 AreaName: string[30];
  57.                 Receivers: array[1..8] of string[12];
  58.                 Key: string[8];
  59.                 PointFeed: boolean;
  60.             end;
  61.         AreaPtr = ^Area;
  62.         AreaHndl = ^AreaPtr;
  63.         AllAreaHandle = array[1..255] of AreaHndl;
  64.         MsgTextLine = STR255;
  65.         MsgTextPtr = ^MsgTextLine;
  66.         MsgTextHndl = ^MsgTextPtr;
  67.         OneString = string;
  68.         OneStringPtr = ^OneString;
  69.         OneStringHndl = ^OneStringPtr;
  70.  
  71.     var
  72.         FlagLine, Ignore, ToName, CapsToName, NodeID, Subject, TextLine, LocalNodeID, SendFileName, OneLine: STR255;
  73.         MessageLine, MessageKey, UserKey, TempLogString: STR255;
  74.         Deletes, Adds: array[1..255] of OneStringHndl;
  75.         FlagPos, logicalEOF, AreaFixEOF, CharsToSend: longint;
  76.         Index, AreaIndex, PointIndex, Counter, Colon, TConfigRef, DeleteCount, AddCount, FilesToDo: integer;
  77.         SendFilesRef, FileCheckRef, GenExpRef, ForwardLogRef, AFWLogRef, ScriptRef: integer;
  78.         AreaArray, PointFeedArray: AllAreaHandle;
  79.         ThisAreaItem, ThisPtItem: Area;
  80.         MsgTextArray: array[1..400] of MsgTextHndl;
  81.         Empty: boolean;
  82.  
  83. { ------------------------------------------------------ }
  84.  
  85.     function BlankStrip (Line: STR255): string;
  86.  
  87.         begin
  88.             while (Line[1] in [SPACE, TAB]) & (length(Line) > 1) do
  89.                 Line := copy(Line, 2, length(Line) - 1);
  90.             while (Line[length(Line)] in [SPACE, TAB]) & (length(Line) > 1) do
  91.                 Line := copy(Line, 1, length(Line) - 1);
  92.             BlankStrip := Line
  93.         end;
  94.  
  95. { ------------------------------------------------------ }
  96.  
  97.     procedure PurgeArea (AnArea: AllAreaHandle; AreaIndex: integer; AreaName, NodeID: STR255);
  98.  
  99.         var
  100.             AreaCount, FeedCount: integer;
  101.  
  102.         begin
  103.             for AreaCount := 1 to AreaIndex do
  104.                 if AnArea[AreaCount]^^.AreaName = AreaName then
  105.                     for FeedCount := 1 to 8 do
  106.                         if AnArea[AreaCount]^^.Receivers[FeedCount] = NodeID then
  107.                             AnArea[AreaCount]^^.Receivers[FeedCount] := ''
  108.         end;
  109.  
  110. { ------------------------------------------------------ }
  111.  
  112.     procedure WriteClosing (FRef: integer);
  113.  
  114.         begin
  115.             MessageLine := '     ';
  116.             Err := MyWriteLine(FRef, MessageLine);
  117.             MessageLine := concat('--- AreaTrix ', TheVers);
  118.             Err := MyWriteLine(FRef, MessageLine);
  119.             MessageLine := NULL;
  120.             Err := MyWriteLine(FRef, MessageLine)
  121.         end;
  122.  
  123. { ------------------------------------------------------ }
  124.  
  125.     procedure WriteHeading (FRef: integer; Pseudonym: str255);
  126.  
  127.         begin
  128.             MessageLine := ' M ';
  129.             Err := MyWriteLine(FRef, MessageLine);                                    {    flags        }
  130.             MessageLine := '000';
  131.             Err := MyWriteLine(FRef, MessageLine);                                    {    category    }
  132.             TimeStamp;
  133.             Err := MyWriteLine(FRef, DateString);                                    {    date        }
  134.             Err := MyWriteLine(FRef, TimeString);                                    {    time        }
  135.             Err := MyWriteLine(FRef, NodeID);                                        {    address    }
  136.             MessageLine := concat(Pseudonym, ' on ', LocalNodeID);
  137.             Err := MyWriteLine(FRef, MessageLine);                                    {    from        }
  138.             Err := MyWriteLine(FRef, FromName);                                        {    to            }
  139.             MessageLine := concat('Reply to ', Pseudonym, ' Request');
  140.             Err := MyWriteLine(FRef, MessageLine)                                    {    subject    }
  141.         end;
  142.  
  143. { ------------------------------------------------------ }
  144.  
  145.     procedure InterpretRequest;
  146.  
  147.         procedure CheckPassword;
  148.  
  149.             var
  150.                 PWRefNum, UserKeyRefNum, SpacePos: integer;
  151.                 PWLine, TempPass1, TempPass2: STR255;
  152.  
  153.             begin
  154.                 if pos(SPACE, Subject) > 1 then
  155.                     TempPass2 := copy(Subject, 1, pos(SPACE, Subject) - 1)
  156.                 else
  157.                     TempPass2 := Subject;
  158.                 Err := FSOpen(':Tabby:AreaPass', vRefNum, PWRefNum);
  159.                 if (Err <> NoErr) then
  160.                     Err := FSOpen(':Tabby:Password', vRefNum, PWRefNum);
  161.                 while not AtEOF(PWRefNum) & not GoodPassword do
  162.                     begin
  163.                         Err := ReadALine(PWRefNum, PWLine);
  164.                         if (pos(NodeID, PWLine) > 0) then
  165.                             begin
  166.                                 TempPass1 := copy(PWLine, pos(TAB, PWLine) + 1, 255);
  167.                                 if TempPass1 = TempPass2 then
  168.                                     GoodPassword := true
  169.                             end        {    if (pos(NodeID, PWLine) > 0)    }
  170.                     end;        {         while not AtEOF(PWRefNum) & not GoodPassword    }
  171.                 Err := FSClose(PWRefNum);
  172.                 UserKey := '';
  173.                 Err := FSOpen(':Tabby:AreaUserKeys', vRefNum, UserKeyRefNum);
  174.                 if Err = NoErr then
  175.                     while (not AtEOF(UserKeyRefNum)) & (Err = NoErr) do
  176.                         begin
  177.                             Err := ReadALine(UserKeyRefNum, TempString);
  178.                             if (pos(NodeId, TempString) > 0) & (Err = NoErr) then
  179.                                 begin
  180.                                     UserKey := BlankStrip(TempString);
  181.                                     UserKey := copy(UserKey, pos(TAB, UserKey) + 1, 255);
  182.                                     UserKey := BlankStrip(UserKey)
  183.                                 end
  184.                         end;
  185.                 Err := FSClose(UserKeyRefNum)
  186.             end;
  187.  
  188.         begin
  189.             GoodPassword := false;
  190.             SendHelp := false;
  191.             SendList := false;
  192.             SendAreas := false;
  193.             if (BlankStrip(Subject) = '?') | (BlankStrip(MsgTextArray[1]^^) = '?') then
  194.                 begin
  195.                     SendHelp := true;
  196.                     Request := true
  197.                 end;
  198.             CheckPassword;
  199.             if (GoodPassword | ListOK) then
  200.                 begin
  201.                     Request := true;
  202.                     UprString(Subject, false);
  203.                     if (pos('-L', Subject) > 0) | (pos('*', MsgTextArray[1]^^) > 0) then
  204.                         SendList := true;
  205.                     if (pos('-Q', Subject) > 0) then
  206.                         SendAreas := true
  207.                 end        {    if GoodPassword    }
  208.             else
  209.                 begin
  210.                     MakeTextFile(concat(GenericPath, 'Generic Export'));
  211.                     Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenericRef);
  212.                     Err := SetFPos(GenericRef, fsFromLEOF, 0);
  213.                     WriteHeading(GenericRef, 'AreaFix');
  214.                     MessageLine := 'You do not have a proper password to use AreaFix, or else you entered the';
  215.                     Err := MyWriteLine(GenericRef, MessageLine);
  216.                     MessageLine := 'password incorrectly. Please ask the System Operator for a password.';
  217.                     Err := MyWriteLine(GenericRef, MessageLine);
  218.                     MessageLine := '     ';
  219.                     Err := MyWriteLine(GenericRef, MessageLine);
  220.                     WriteClosing(GenericRef);
  221.                     Err := FSClose(GenericRef);
  222.                 end        {    good Password or ListOK    }
  223.         end;
  224.  
  225. { ------------------------------------------------------ }
  226.  
  227.     function ReadAreaLine (LeftOver: STR255): Area;
  228.  
  229.         var
  230.             PlaceMark, StringIndex, NodeIndex, TempCount: integer;
  231.             TempArea: Area;
  232.             PointSwitch: STR255;
  233.  
  234.         begin
  235.             TempArea.AreaName := '';
  236.             PlaceMark := pos(TAB, LeftOver);
  237.             if (PlaceMark > 1) then
  238.                 begin
  239.                     TempArea.AreaNum := copy(LeftOver, 1, PlaceMark - 1);
  240.                     PointSwitch := concat('0/', TempArea.AreaNum);    {    Feeds to point are of form 0/AreaNum    }
  241.                     LeftOver := copy(LeftOver, PlaceMark + 1, length(LeftOver) - PlaceMark);
  242.                     UprString(LeftOver, false);
  243.                     PlaceMark := pos(TAB, LeftOver);
  244.                     if (PlaceMark > 1) then
  245.                         begin
  246.                             TempArea.AreaName := copy(LeftOver, 1, PlaceMark - 1);
  247.                             LeftOver := copy(LeftOver, PlaceMark + 1, length(LeftOver) - PlaceMark);
  248.                             StringIndex := 1;
  249.                             NodeIndex := 1;
  250.                             for TempCount := 1 to 8 do
  251.                                 TempArea.Receivers[TempCount] := '';
  252.                             while StringIndex <= length(LeftOver) do
  253.                                 begin
  254.                                     while (LeftOver[StringIndex] <> SPACE) & (StringIndex <= length(LeftOver)) do
  255.                                         begin
  256.                                             TempArea.Receivers[NodeIndex] := concat(TempArea.Receivers[NodeIndex], LeftOver[StringIndex]);
  257.                                             StringIndex := succ(StringIndex);
  258.                                         end;        {    while LeftOver[StringIndex] <> chr(32)) & (StringIndex <= length(LeftOver)    }
  259.                                     if pos(PointSwitch, TempArea.Receivers[NodeIndex]) = 1 then
  260.                                         TempArea.PointFeed := true
  261.                                     else
  262.                                         TempArea.PointFeed := false;
  263.                                     StringIndex := succ(StringIndex);
  264.                                     NodeIndex := succ(NodeIndex);
  265.                                     TempArea.Key := '';
  266.                                 end        {    while StringIndex <= length(LeftOver)    }
  267.                         end        {    if (PlaceMark > 1)    }
  268.                 end;        {    if (PlaceMark > 1)    }
  269.             ReadAreaLine := TempArea
  270.         end;
  271.  
  272. { ------------------------------------------------------ }
  273.  
  274.     procedure ReadAreas;
  275.  
  276.         var
  277.             AreasRef, Counter: integer;
  278.             AreaEOF: longint;
  279.             TempLine, AreaName, AreaKey: STR255;
  280.             TempArea: Area;
  281.  
  282.         begin
  283.             AreaIndex := 0;
  284.             Err := FSOpen(':Tabby:areas.bbs', vRefNum, AreasRef);
  285.             if Err = NoErr then
  286.                 while (not AtEOF(AreasRef)) do
  287.                     begin
  288.                         Err := ReadALine(AreasRef, TempLine);
  289.                         if AreaIndex > 0 then        {    This skips the first line    }
  290.                             begin
  291.                                 TempArea := ReadAreaLine(TempLine);
  292.                                 if TempArea.AreaName <> '' then
  293.                                     begin
  294.                                         AreaArray[AreaIndex] := AreaHndl(NewHandle(sizeOf(Area)));
  295.                                         HLock(Handle(AreaArray[AreaIndex]));
  296.                                         AreaArray[AreaIndex]^^ := TempArea;
  297.                                         AreaIndex := succ(AreaIndex)
  298.                                     end        {    if TempArea.AreaName <> ''    }
  299.                             end        {    if AreaIndex > 0                    }
  300.                         else
  301.                             AreaIndex := succ(AreaIndex)
  302.                     end;    {    while (AreaLoc < AreaEOF)            }
  303.             AreaIndex := pred(AreaIndex);
  304.             Err := FSClose(AreasRef);
  305.             Err := FSOpen(':Tabby:AreaKeys', vRefNum, AreasRef);
  306.             if Err = NoErr then
  307.                 begin
  308.                     while not AtEOF(AreasRef) do
  309.                         begin
  310.                             Err := ReadALine(AreasRef, TempLine);
  311.                             if (pos(TAB, TempLine) > 0) & (length(TempLine) > 0) then
  312.                                 begin
  313.                                     TempLine := BlankStrip(TempLine);
  314.                                     AreaName := copy(TempLine, 1, pos(TAB, Templine) - 1);
  315.                                     AreaName := BlankStrip(AreaName);
  316.                                     AreaKey := copy(TempLine, pos(TAB, Templine) + 1, 255);
  317.                                     AreaKey := BlankStrip(AreaKey);
  318.                                     for Counter := 1 to AreaIndex do
  319.                                         if AreaArray[Counter]^^.AreaName = AreaName then
  320.                                             AreaArray[Counter]^^.Key := copy(AreaKey, 1, 8)
  321.                                 end        {    if (pos(TAB, TempLine) > 0) & (length(TempLine) > 0)    }
  322.                         end;    {    while not at eof AreaKeys    }
  323.                     Err := FSClose(AreasRef)
  324.                 end    {    no error opening AreaKeys file    }
  325.         end;
  326.  
  327. { ------------------------------------------------------ }
  328.  
  329.     procedure ReadPointFeeds;
  330.  
  331.         var
  332.             PointsRef: integer;
  333.             AreaEOF: longint;
  334.             TempLine: STR255;
  335.             TempArea: Area;
  336.  
  337.         begin
  338.             PointIndex := 1;
  339.             Err := FSOpen(':Tabby:PointGroups', vRefNum, PointsRef);
  340.             if Err = NoErr then
  341.                 while (not AtEOF(PointsRef)) do
  342.                     begin
  343.                         Err := ReadALine(PointsRef, TempLine);
  344.                         TempArea := ReadAreaLine(TempLine);
  345.                         if TempArea.AreaName <> '' then
  346.                             begin
  347.                                 PointFeedArray[PointIndex] := AreaHndl(NewHandle(sizeOf(Area)));
  348.                                 HLock(Handle(PointFeedArray[PointIndex]));
  349.                                 PointFeedArray[PointIndex]^^ := TempArea;
  350.                                 PointIndex := succ(PointIndex)
  351.                             end        {    if TempArea.AreaName <> ''    }
  352.                     end;        {    while (AreaLoc < AreaEOF)    }
  353.             PointIndex := pred(PointIndex);
  354.             Err := FSClose(PointsRef)
  355.         end;
  356.  
  357. { ------------------------------------------------------ }
  358.  
  359.     function Clean (Line: STR255): string;
  360.  
  361.         begin
  362.             while (Line[1] in [SPACE, TAB, '+', '-']) & (length(Line) > 1) do
  363.                 Line := copy(Line, 2, length(Line) - 1);
  364.             while (Line[length(Line)] in [SPACE, TAB]) & (length(Line) > 1) do
  365.                 Line := copy(Line, 1, length(Line) - 1);
  366.             uprString(Line, false);
  367.             Clean := Line
  368.         end;
  369.  
  370. { ------------------------------------------------------ }
  371.  
  372.     procedure UpdateAreaFile (FileName: STR255; AreaArray: AllAreaHandle; AreaIndex: integer);
  373.  
  374.         var
  375.             AreasRef, BakRef, AreaCount, DlvrCount, DupeCount, First, Current, Least: integer;
  376.             AreasLine: str255;
  377.             CurrentSect, LeastSect: longint;
  378.  
  379.         begin
  380.             Err := FSDelete(concat(FileName, '.bak'), vRefNum);
  381.             Err := Rename(FileName, vRefNum, concat(FileName, '.bak'));
  382.             Err := Create(FileName, vRefNum, 'QED1', 'TEXT');
  383.             Err := FSOpen(FileName, vRefNum, AreasRef);
  384.             Err := SetFPos(AreasRef, fsFromStart, 0);
  385.             if FileName = ':Tabby:areas.bbs' then            {    Read and write BBS ID line    }
  386.                 begin
  387.                     Err := FSOpen(concat(FileName, '.bak'), vRefNum, BakRef);
  388.                     Err := ReadALine(BakRef, AreasLine);        {    Read BBS ID line    }
  389.                     Err := FSClose(BakRef);
  390.                     Err := MyWriteLine(AreasRef, AreasLine)
  391.                 end;
  392.  
  393. {    organize AreaArray by Areanum using selection sort [Oh! Pascal pg. 528]    }
  394.  
  395.             for First := 1 to AreaIndex - 1 do
  396.                 begin
  397.                     Least := First;        {    Guess that this is the least value    }
  398.                     for Current := First + 1 to AreaIndex do
  399.                         begin
  400.                             if AreaArray[Current]^^.AreaName = 'UNKNOWN' then                    {make sure it's sorted to last place}
  401.                                 CurrentSect := 1000
  402.                             else if AreaArray[Current]^^.AreaNum = '***' then                    {put pass-thrus after others, before Unknown}
  403.                                 CurrentSect := 300 + ord(AreaArray[Current]^^.AreaName[1])    {alphabetic by first char}
  404.                             else
  405.                                 StringToNum(AreaArray[Current]^^.AreaNum, CurrentSect);
  406.                             if AreaArray[Least]^^.AreaName = 'UNKNOWN' then                    {make sure it's sorted to last place}
  407.                                 LeastSect := 1000
  408.                             else if AreaArray[Least]^^.AreaNum = '***' then                    {put pass-thrus after others, before Unknown}
  409.                                 LeastSect := 300 + ord(AreaArray[Least]^^.AreaName[1])            {alphabetic by first char}
  410.                             else
  411.                                 StringToNum(AreaArray[Least]^^.AreaNum, LeastSect);
  412.                             if CurrentSect < LeastSect then
  413.                                 Least := Current
  414.                         end;
  415.                     ThisAreaItem := AreaArray[Least]^^;        {    Swap AreaArray[First] and AreaArray[Least]    }
  416.                     AreaArray[Least]^^ := AreaArray[First]^^;
  417.                     AreaArray[First]^^ := ThisAreaItem
  418.                 end;
  419.  
  420. {    next routine kills dupe entries    }
  421.  
  422.             for AreaCount := 1 to AreaIndex do
  423.                 for DlvrCount := 1 to 8 do
  424.                     for DupeCount := (DlvrCount + 1) to 8 do
  425.                         if AreaArray[AreaCount]^^.Receivers[DlvrCount] = AreaArray[AreaCount]^^.Receivers[DupeCount] then
  426.                             AreaArray[AreaCount]^^.Receivers[DupeCount] := '';
  427.  
  428. {    next routine puts "0/x" entries at end    }
  429.  
  430.             for AreaCount := 1 to AreaIndex do
  431.                 for DlvrCount := 1 to 7 do
  432.                     if AreaArray[AreaCount]^^.Receivers[DlvrCount] = concat('0/', AreaArray[AreaCount]^^.AreaNum) then
  433.                         if AreaArray[AreaCount]^^.Receivers[8] = '' then
  434.                             begin
  435.                                 AreaArray[AreaCount]^^.Receivers[8] := concat('0/', AreaArray[AreaCount]^^.AreaNum);
  436.                                 AreaArray[AreaCount]^^.Receivers[DlvrCount] := ''
  437.                             end
  438.                         else
  439.                             begin
  440.                                 AreaArray[AreaCount]^^.Receivers[DlvrCount] := AreaArray[AreaCount]^^.Receivers[8];
  441.                                 AreaArray[AreaCount]^^.Receivers[8] := concat('0/', AreaArray[AreaCount]^^.AreaNum)
  442.                             end;
  443.  
  444.             for AreaCount := 1 to AreaIndex do
  445.                 begin
  446.                     AreasLine := concat(AreaArray[AreaCount]^^.Areanum, TAB, AreaArray[AreaCount]^^.AreaName, TAB);
  447.                     for DlvrCount := 1 to 8 do
  448.                         if (length(AreaArray[AreaCount]^^.Receivers[DlvrCount]) > 0) then
  449.                             AreasLine := concat(AreasLine, AreaArray[AreaCount]^^.Receivers[DlvrCount], SPACE);
  450.                     if AreasLine[length(AreasLine)] = SPACE then
  451.                         AreasLine := copy(AreasLine, 1, length(AreasLine) - 1);
  452.                     Err := MyWriteLine(AreasRef, AreasLine)
  453.                 end;        {    for AreaCount := 1 to AreaIndex    }
  454.             Err := GetFPos(AreasRef, logicalEOF);
  455.             Err := SetEOF(AreasRef, logicalEOF);
  456.             Err := FSClose(AreasRef)
  457.         end;
  458.  
  459. { ------------------------------------------------------ }
  460.  
  461.     procedure AlterAreas;
  462.  
  463.         var
  464.             MLineCount, AlterCount, DlvrCount, AreasRef, AreaCount, PtCount, DlvrPtCount, Count2: integer;
  465.             AreaEOF, Ptlongint, TestLongint: longint;
  466.             AreaString, TextString, StrippedMsgText, PointNo: string;
  467.             AreasLine: STR255;
  468.             Changed: boolean;
  469.  
  470.         begin
  471.             DeleteCount := 0;
  472.             AddCount := 0;
  473.             if UserKey <> '' then        {    if sysop entered a user key, it overrides    }
  474.                 MessageKey := UserKey
  475.             else
  476.                 MessageKey := '';
  477.             for MLineCount := 1 to Index do
  478.                 begin
  479.                     StrippedMsgText := Clean(MsgTextArray[MLineCount]^^);
  480.                     if (StrippedMsgText <> '*') & (StrippedMsgText <> '?') then
  481.                         begin
  482.                             Changed := false;
  483.                             if (MLineCount = 1) & (pos('KEY:', StrippedMsgText) > 0) & (MessageKey = '') then
  484.                                 begin
  485.         {    next line keeps original case of message line for more keyword flexibility. We know    }
  486.         {    the line contains the word 'Key:' in some case, but we target only the colon for        }
  487.         {    simplicity.                                                                                                    }
  488.                                     MessageKey := copy(MsgTextArray[1]^^, pos(':', MsgTextArray[1]^^) + 1, 255);
  489.                                     MessageKey := BlankStrip(MessageKey);
  490.                                 end
  491.                             else
  492.                                 begin
  493.                                     for AlterCount := 1 to AreaIndex do
  494.                                         begin
  495.                                             ThisAreaItem := AreaArray[AlterCount]^^;
  496.                                             if (ThisAreaItem.AreaName = StrippedMsgText) then
  497.                                                 if (ThisAreaItem.Key = '') | (pos(ThisAreaItem.Key, MessageKey) > 0) then
  498.                                                     if (pos('-', MsgTextArray[MLineCount]^^) = 1) then
  499.                                                         begin
  500.                                                             if FromPoint & ThisAreaItem.PointFeed then
  501.                                                                 begin
  502.                                                                     PointNo := copy(NodeID, pos('/', NodeID) + 1, 255);    {Get point number}
  503.                                                                     StringToNum(PointNo, PtLongint);
  504. {        Check & see if it's possible to remove from point feed        }
  505.                                                                     for PtCount := 1 to PointIndex do
  506.                                                                         begin
  507.                                                                             ThisPtItem := PointFeedArray[PtCount]^^;
  508.                                                                             if (ThisPtItem.AreaName = StrippedMsgText) then
  509.                                                                                 for DlvrPtCount := 1 to 8 do
  510.                                                                                     begin
  511. {        Remember that points are stored by numbers only, not complete addresses!!!        }
  512.                                                                                         StringToNum(ThisPtItem.Receivers[DlvrPtCount], TestLongint);
  513.                                                                                         if TestLongint = PtLongint then
  514.                                                                                             begin
  515.                                                                                                 PointFeedArray[PtCount]^^.Receivers[DlvrPtCount] := '';
  516.                                                                                                 DeleteCount := succ(DeleteCount);
  517.                                                                                                 Deletes[DeleteCount] := OneStringHndl(NewHandle(sizeOf(OneString)));
  518.                                                                                                 Deletes[DeleteCount]^^ := ThisPtItem.AreaName;
  519.                                                                                                 PurgeArea(AreaArray, AreaIndex, StrippedMsgText, NodeID);    {    Get rid of Areas.bbs refs    }
  520.                                                                                                 Changed := true;
  521.                                                                                                 Leave    {    done: exit DlvrPtCount := 1 to 8 loop    }
  522.                                                                                             end
  523.                                                                                     end        {    for DlvrPtCount := 1 to 8    }
  524.                                                                         end        {    for PtCount := 1 to PointIndex        }
  525.                                                                 end;    {    if FromPoint & ThisAreaItem.PointFeed        }
  526.  
  527.                                                             if not Changed then
  528.                                                                 for DlvrCount := 2 to 8 do        {    Start at 2 so not to delete feed    }
  529.                                                                     if (pos(NodeID, AreaArray[AlterCount]^^.Receivers[DlvrCount]) > 0) & (length(AreaArray[AlterCount]^^.Receivers[DlvrCount]) > 0) then
  530.                                                                         begin
  531.                                                                             AreaArray[AlterCount]^^.Receivers[DlvrCount] := '';
  532.                                                                             DeleteCount := succ(DeleteCount);
  533.                                                                             Deletes[DeleteCount] := OneStringHndl(NewHandle(sizeOf(OneString)));
  534.                                                                             Deletes[DeleteCount]^^ := ThisAreaItem.AreaName;
  535.                                                                             Changed := true;
  536.                                                                             Leave
  537.                                                                         end
  538.                                                         end        {    if (pos('-', MsgTextArray[MLineCount]^^) = 1)    }
  539.                                                     else
  540.                                                         begin    {    Need to add it        }
  541.                                                             if FromPoint & ThisAreaItem.PointFeed then
  542.                                                                 begin
  543.                                                                     PurgeArea(AreaArray, AreaIndex, StrippedMsgText, NodeID);    {    Get rid of Areas.bbs refs    }
  544.                                                                     PointNo := copy(NodeID, pos('/', NodeID) + 1, 255);    {Get point number}
  545.                                                                     StringToNum(PointNo, PtLongint);
  546.     {    Check & see if it's possible to add to point feed        }
  547.                                                                     for PtCount := 1 to PointIndex do
  548.                                                                         begin
  549.                                                                             ThisPtItem := PointFeedArray[PtCount]^^;
  550.                                                                             if (ThisPtItem.AreaName = StrippedMsgText) then
  551.                                                                                 begin
  552.                                                                                     for DlvrPtCount := 1 to 8 do        {    Purge list of this NodeID    }
  553.                                                                                         begin
  554.                                                                                             StringToNum(ThisPtItem.Receivers[DlvrPtCount], TestLongint);
  555.                                                                                             if TestLongint = PtLongint then
  556.                                                                                                 PointFeedArray[PtCount]^^.Receivers[DlvrPtCount] := ''
  557.                                                                                         end;
  558.  
  559.                                                                                     for DlvrPtCount := 1 to 8 do        {    Now add it to the first empty spot    }
  560.                                                                                         if (length(PointFeedArray[PtCount]^^.Receivers[DlvrPtCount]) = 0) then
  561.                                                                                             begin
  562.                                                                                                 PointFeedArray[PtCount]^^.Receivers[DlvrPtCount] := PointNo;
  563.                                                                                                 AddCount := succ(AddCount);
  564.                                                                                                 Adds[AddCount] := OneStringHndl(NewHandle(sizeOf(OneString)));
  565.                                                                                                 Adds[AddCount]^^ := ThisPtItem.AreaName;
  566.                                                                                                 Changed := true;
  567.                                                                                                 Leave            {    added NodeId, so exit loop        }
  568.                                                                                             end;        {    for DlvrPtCount := 1 to 8    }
  569.  
  570.                                                                                 end;        {    if (ThisPtItem.AreaName = StrippedMsgText)    }
  571.                                                                             if Changed then
  572.                                                                                 leave;
  573.                                                                         end;        {    for PtCount := 1 to PointIndex                }
  574.  
  575.                                                                     if not Changed then     {    no room in existing PointFeedArray, so add new one    }
  576.                                                                         begin
  577.                                                                             TempString := '';
  578.                                                                             for Count2 := 1 to AreaIndex do            {    Get the area number for this section    }
  579.                                                                                 if AreaArray[Count2]^^.AreaName = StrippedMsgText then
  580.                                                                                     begin
  581.                                                                                         TempString := AreaArray[Count2]^^.AreaNum;
  582.                                                                                         Leave
  583.                                                                                     end;
  584.                                                                             if TempString <> '' then
  585.                                                                                 begin
  586.                                                                                     PointIndex := succ(PointIndex);
  587.                                                                                     PointFeedArray[PointIndex] := AreaHndl(NewHandle(sizeOf(Area)));
  588.                                                                                     HLock(Handle(PointFeedArray[PointIndex]));
  589.                                                                                     PointFeedArray[PointIndex]^^.AreaNum := TempString;
  590.                                                                                     PointFeedArray[PointIndex]^^.AreaName := StrippedMsgText;
  591.                                                                                     for Count2 := 1 to 8 do
  592.                                                                                         PointFeedArray[PointIndex]^^.Receivers[Count2] := '';
  593.                                                                                     PointFeedArray[PointIndex]^^.Receivers[1] := PointNo;
  594.                                                                                     PointFeedArray[PointIndex]^^.PointFeed := true;
  595.                                                                                     AddCount := succ(AddCount);
  596.                                                                                     Adds[AddCount] := OneStringHndl(NewHandle(sizeOf(OneString)));
  597.                                                                                     Adds[AddCount]^^ := ThisPtItem.AreaName;
  598.                                                                                     Changed := true
  599.                                                                                 end;        {    if TempString <> ''    }
  600.                                                                         end;        {    if not Changed        }
  601.  
  602.                                                                 end;    {    if FromPoint & ThisAreaItem.PointFeed                }
  603.  
  604.                                                             if not Changed then
  605.                                                                 begin
  606.                                                                     for DlvrCount := 1 to 8 do        {    Purge list of this NodeID    }
  607.                                                                         if (pos(NodeID, ThisAreaItem.Receivers[DlvrCount]) > 0) then
  608.                                                                             AreaArray[AlterCount]^^.Receivers[DlvrCount] := '';
  609.                                                                     for DlvrCount := 1 to 8 do        {    Now add it to the first empty spot    }
  610.                                                                         if (length(ThisAreaItem.Receivers[DlvrCount]) = 0) then
  611.                                                                             begin
  612.                                                                                 AreaArray[AlterCount]^^.Receivers[DlvrCount] := NodeID;
  613.                                                                                 AddCount := succ(AddCount);
  614.                                                                                 Adds[AddCount] := OneStringHndl(NewHandle(sizeOf(OneString)));
  615.                                                                                 Adds[AddCount]^^ := ThisAreaItem.AreaName;
  616.                                                                                 Leave            {    added NodeId, so exit loop        }
  617.                                                                             end        {    for DlvrCount := 1 to 8    }
  618.                                                                 end        {    if not Changed    }
  619.                                                         end        {    if (pos('-', MsgTextArray[MLineCount]^^) <> 1) [else clause]    }
  620.                                         end        {    for AlterCount := 1 to AreaIndex    }
  621.                                 end        {    if pos('KEY',MsgTextArray) = 0        }
  622.                         end        {    if (StrippedMsgText <> '*') & (StrippedMsgText <> '?')    }
  623.                     else
  624.                         SendAreas := true;        {    User entered an asterisk to get listing    }
  625.                 end        {    for MLineCount := 1 to Index    }
  626.         end;
  627.  
  628. { ------------------------------------------------------ }
  629.  
  630.     procedure SendMsg (Pseudonym: str255);
  631.  
  632.         var
  633.             AlterCount, DlvrCount, EchoIndex, ListRef, HelpRef: integer;
  634.             PointNo: str255;
  635.             CharsToRead: longint;
  636.             Available: boolean;
  637.  
  638.         begin
  639.             MakeTextFile(concat(GenericPath, 'Generic Export'));
  640.             if GoodPassword then
  641.                 begin
  642.                     MakeTextFile(concat(GenericPath, 'Generic Export'));
  643.                     Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenericRef);
  644.                     Err := SetFPos(GenericRef, fsFromLEOF, 0);
  645.                     WriteHeading(GenericRef, 'AreaFix');
  646.                     MessageLine := 'You are currently sharing the following Echoes with this board (an asterisk';
  647.                     Err := MyWriteLine(GenericRef, MessageLine);
  648.                     MessageLine := 'indicates that you are the feed):';
  649.                     Err := MyWriteLine(GenericRef, MessageLine);
  650.                     MessageLine := '     ';
  651.                     Err := MyWriteLine(GenericRef, MessageLine);
  652.  
  653.                     for AlterCount := 1 to AreaIndex do
  654.                         if (AreaArray[AlterCount]^^.Key = '') | (pos(AreaArray[AlterCount]^^.Key, MessageKey) > 0) then
  655.                             for DlvrCount := 1 to 8 do
  656.                                 if (pos(NodeID, AreaArray[AlterCount]^^.Receivers[DlvrCount])) > 0 then
  657.                                     begin
  658.                                         if DlvrCount = 1 then
  659.                                             MessageLine := '* '
  660.                                         else
  661.                                             MessageLine := '  ';
  662.                                         Err := MyWrite(GenericRef, MessageLine);
  663.                                         MessageLine := AreaArray[AlterCount]^^.AreaName;
  664.                                         Err := MyWriteLine(GenericRef, MessageLine);
  665.                                         leave;        {    found a node match, so exit the for loop    }
  666.                                     end;        {    if (pos(NodeID, AreaArray[AlterCount]^^.Receivers[DlvrCount])) > 0    }
  667.  
  668.                     if pos(PointNetString, NodeID) <> 0 then
  669.                         begin
  670.                             PointNo := copy(NodeID, pos('/', NodeID) + 1, 255);    {Get point number}
  671.                             for AlterCount := 1 to PointIndex do
  672.                                 if (PointFeedArray[AlterCount]^^.Key = '') | (pos(PointFeedArray[AlterCount]^^.Key, MessageKey) > 0) then
  673.                                     for DlvrCount := 1 to 8 do
  674.                                         if (pos(PointNo, PointFeedArray[AlterCount]^^.Receivers[DlvrCount])) > 0 then
  675.                                             begin
  676.                                                 MessageLine := concat('  ', PointFeedArray[AlterCount]^^.AreaName);
  677.                                                 Err := MyWriteLine(GenericRef, MessageLine);
  678.                                                 leave        {    found a node match, so exit the for loop    }
  679.                                             end        {    if (pos(NodeID, PointFeedArray[AlterCount]^^.Receivers[DlvrCount])) > 0    }
  680.                         end;        {    if pos(PointNetString, NodeID) <> 0    }
  681.  
  682.                     if AddCount > 0 then
  683.                         begin
  684.                             MessageLine := '     ';
  685.                             Err := MyWriteLine(GenericRef, MessageLine);
  686.                             MessageLine := 'At your request, the following Echo feeds were added:';
  687.                             Err := MyWriteLine(GenericRef, MessageLine);
  688.                             MessageLine := '     ';
  689.                             Err := MyWriteLine(GenericRef, MessageLine);
  690.                             for AlterCount := 1 to AddCount do
  691.                                 if length(Adds[AlterCount]^^) > 0 then
  692.                                     begin
  693.                                         MessageLine := concat('  ', Adds[AlterCount]^^);
  694.                                         Err := MyWriteLine(GenericRef, MessageLine);
  695.                                     end;
  696.                         end;        {    if AddCount > 0    }
  697.  
  698.                     if DeleteCount > 0 then
  699.                         begin
  700.                             MessageLine := '     ';
  701.                             Err := MyWriteLine(GenericRef, MessageLine);
  702.                             MessageLine := 'At your request, the following Echo feeds were discontinued:';
  703.                             Err := MyWriteLine(GenericRef, MessageLine);
  704.                             MessageLine := '     ';
  705.                             Err := MyWriteLine(GenericRef, MessageLine);
  706.                             for AlterCount := 1 to DeleteCount do
  707.                                 if length(Deletes[AlterCount]^^) > 0 then
  708.                                     begin
  709.                                         MessageLine := concat('  ', Deletes[AlterCount]^^);
  710.                                         Err := MyWriteLine(GenericRef, MessageLine);
  711.                                     end;
  712.                         end;        {    if DeleteCount > 0    }
  713.  
  714.                     WriteClosing(GenericRef);
  715.                     Err := FSClose(GenericRef);
  716.  
  717.                     if ((DeleteCount > 0) | (AddCount > 0)) & MsgToSysop then
  718.                         begin
  719.                             MakeTextFile(concat(GenericPath, 'Generic Import'));
  720.                             Err := FSOpen(concat(GenericPath, 'Generic Import'), vRefNum, GenericRef);
  721.                             Err := SetFPos(GenericRef, fsFromLEOF, 0);
  722.                             MessageLine := ' M ';
  723.                             Err := MyWriteLine(GenericRef, MessageLine);
  724.                             MessageLine := '000';
  725.                             Err := MyWriteLine(GenericRef, MessageLine);
  726.                             TimeStamp;
  727.                             Err := MyWriteLine(GenericRef, DateString);
  728.                             Err := MyWriteLine(GenericRef, TimeString);
  729.                             Err := MyWriteLine(GenericRef, LocalNodeID);
  730.                             MessageLine := concat('AreaFix on ', LocalNodeID);
  731.                             Err := MyWriteLine(GenericRef, MessageLine);
  732.                             MessageLine := 'Sysop';
  733.                             Err := MyWriteLine(GenericRef, MessageLine);
  734.                             MessageLine := 'Notice of AreaFix Request';
  735.                             Err := MyWriteLine(GenericRef, MessageLine);
  736.                             MessageLine := concat('At the request of ', FromName, ' at ', NodeID, ', these changes were');
  737.                             Err := MyWriteLine(GenericRef, MessageLine);
  738.                             MessageLine := 'made to Echo distribution:';
  739.                             Err := MyWriteLine(GenericRef, MessageLine);
  740.                             MessageLine := '     ';
  741.                             Err := MyWriteLine(GenericRef, MessageLine);
  742.  
  743.                             if AddCount > 0 then
  744.                                 begin
  745.                                     for AlterCount := 1 to AddCount do
  746.                                         if length(Adds[AlterCount]^^) > 0 then
  747.                                             begin
  748.                                                 MessageLine := concat('Added........ ', Adds[AlterCount]^^);
  749.                                                 Err := MyWriteLine(GenericRef, MessageLine);
  750.                                             end;
  751.                                 end;        {    if AddCount > 0    }
  752.  
  753.                             if DeleteCount > 0 then
  754.                                 begin
  755.                                     if AddCount > 0 then
  756.                                         begin
  757.                                             MessageLine := '     ';
  758.                                             Err := MyWriteLine(GenericRef, MessageLine);
  759.                                         end;
  760.                                     for AlterCount := 1 to DeleteCount do
  761.                                         if length(Deletes[AlterCount]^^) > 0 then
  762.                                             begin
  763.                                                 MessageLine := concat('Deleted...... ', Deletes[AlterCount]^^);
  764.                                                 Err := MyWriteLine(GenericRef, MessageLine);
  765.                                             end;
  766.                                 end;        {    if DeleteCount > 0    }
  767.  
  768.                             WriteClosing(GenericRef);
  769.                             Err := FSClose(GenericRef);
  770.                         end;        {       if ((DeleteCount > 0) | (AddCount > 0)) & MsgToSysop    }
  771.                 end;        {    if GoodPassword    }
  772.  
  773.             if SendList then
  774.                 begin
  775.                     Err := FSOpen(concat(':Tabby:AreaFix.List'), vRefNum, ListRef);
  776.                     if Err <> NoErr then
  777.                         Err := FSOpen(concat(':Tabby:AreaTrix.List'), vRefNum, ListRef);
  778.                     if Err = NoErr then
  779.                         Err := GetEOF(ListRef, logicalEOF);
  780.                     if Err = NoErr then
  781.                         begin
  782.                             MakeTextFile(concat(GenericPath, 'Generic Export'));
  783.                             Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenericRef);
  784.                             Err := SetFPos(GenericRef, fsFromLEOF, 0);
  785.                             WriteHeading(GenericRef, 'AreaFix');
  786.                             MessageLine := 'The following is a list of Echoes carried by this board:';
  787.                             Err := MyWriteLine(GenericRef, MessageLine);
  788.                             MessageLine := '     ';
  789.                             Err := MyWriteLine(GenericRef, MessageLine);
  790.                             while not AtEOF(ListRef) do
  791.                                 begin
  792.                                     Err := ReadALine(ListRef, MessageLine);
  793.                                     TempString := BlankStrip(MessageLine);
  794.                                     if pos(' ', TempString) > 0 then
  795.                                         begin
  796.                                             TempString := copy(TempString, 1, pos(' ', TempString) - 1);    {    AreaName is in TempString    }
  797.                                             UprString(TempString, false);
  798.                                             for AlterCount := 1 to AreaIndex do
  799.                                                 if (AreaArray[AlterCount]^^.AreaName = TempString) then
  800.                                                     if (AreaArray[AlterCount]^^.Key = '') | (pos(AreaArray[AlterCount]^^.Key, MessageKey) > 0) then
  801.                                                         begin
  802.                                                             Err := MyWriteLine(GenericRef, MessageLine);
  803.                                                             leave    {    AlterCount loop    }
  804.                                                         end
  805.                                         end        {    if pos(' ', TempString) > 0        }
  806.                                 end;        {        while not AtEOF(ListRef)    }
  807.                             WriteClosing(GenericRef);
  808.                             Err := FSClose(GenericRef);
  809.                         end;        {    if Err = NoErr for AreaFix.List    }
  810.                     Err := FSClose(ListRef);
  811.                 end;        {    if SendList    }
  812.  
  813.             if SendAreas then
  814.                 begin
  815.                     MakeTextFile(concat(GenericPath, 'Generic Export'));
  816.                     Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenericRef);
  817.                     Err := SetFPos(GenericRef, fsFromLEOF, 0);
  818.                     WriteHeading(GenericRef, 'AreaFix');
  819.                     MessageLine := 'The following is a list of Echoes currently available on this board:';
  820.                     Err := MyWriteLine(GenericRef, MessageLine);
  821.                     MessageLine := '     ';
  822.                     Err := MyWriteLine(GenericRef, MessageLine);
  823.                     for EchoIndex := 1 to AreaIndex do
  824.                         begin
  825.                             with AreaArray[EchoIndex]^^ do
  826.                                 begin
  827.                                     Available := false;
  828.                                     for DlvrCount := 1 to 8 do
  829.                                         if Receivers[DlvrCount] = '' then
  830.                                             Available := true;
  831.                                     if Available & (AreaName <> 'UNKNOWN') then
  832.                                         if (AreaArray[EchoIndex]^^.Key = '') | (pos(AreaArray[EchoIndex]^^.Key, MessageKey) > 0) then
  833.                                             begin
  834.                                                 MessageLine := AreaName;
  835.                                                 Err := MyWriteLine(GenericRef, MessageLine);
  836.                                             end;            {    if Available    }
  837.                                 end;        {    with AreaArry[EchoIndex]^^    }
  838.                         end;        {    for EchoIndex := 1 to AreaIndex    }
  839.                     WriteClosing(GenericRef);
  840.  
  841.                     Err := FSClose(GenericRef)
  842.                 end;        {    if SendAreas    }
  843.  
  844.             if SendHelp then
  845.                 begin
  846.                     MakeTextFile(concat(GenericPath, 'Generic Export'));
  847.                     Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenericRef);
  848.                     if Err = NoErr then
  849.                         begin
  850.                             Err := SetFPos(GenericRef, fsFromLEOF, 0);
  851.                             WriteHeading(GenericRef, 'AreaFix');
  852.                         end;
  853.                     Err := FSOpen(concat(':Tabby:AreaTrix Help'), vRefNum, HelpRef);
  854.                     if Err = NoErr then
  855.                         begin
  856.                             Err := SetFPos(HelpRef, fsFromStart, 0);
  857.                             while not AtEOF(HelpRef) do
  858.                                 begin
  859.                                     Err := ReadALine(HelpRef, MessageLine);
  860.                                     if Err = NoErr then
  861.                                         Err := MyWriteLine(GenericRef, MessageLine)
  862.                                 end
  863.                         end;
  864.                     if Err = NoErr then
  865.                         WriteClosing(GenericRef);
  866.                     Err := FSClose(GenericRef);
  867.                     Err := FSClose(HelpRef)
  868.                 end;        {    if SendHelp    }
  869.  
  870.             if GoodPassword then
  871.                 begin
  872.  
  873.                     for AlterCount := 1 to AddCount do
  874.                         DisposHandle(Handle(Adds[AlterCount]));
  875.  
  876.                     for AlterCount := 1 to DeleteCount do
  877.                         DisposHandle(Handle(Deletes[AlterCount]))
  878.  
  879.                 end        {    if GoodPassword    }
  880.         end;
  881.  
  882. { ------------------------------------------------------ }
  883.  
  884.     procedure CheckPoint;
  885.  
  886. {    Checks NodeID field of message to see if it came from a member of the local    }
  887. {    point network.                                                        }
  888.  
  889.         var
  890.             NetPos, SlashPos: integer;
  891.  
  892.         begin
  893.             NetPos := pos(PointNetString, NodeID);
  894.             SlashPos := pos('/', NodeID);
  895.             if (NetPos = 1) & (SlashPos = length(PointNetString) + 1) then
  896.                 FromPoint := true
  897.             else
  898.                 FromPoint := false
  899.         end;
  900.  
  901. { ------------------------------------------------------ }
  902.  
  903.     procedure DoFileForward;
  904.  
  905.         var
  906.             FilesToDo: integer;
  907.  
  908.         begin
  909.             InterpretRequest;        {    Just want to make sure we've got a good password    }
  910.             if GoodPassword & (pos('>', Subject) > 0) then
  911.                 begin
  912.                     Subject := BlankStrip(Subject);
  913.                     Subject := copy(Subject, pos('>', Subject) + 1, 255);
  914.                     Subject := BlankStrip(Subject);
  915.                     if pos('/', Subject) = 0 then
  916.                         Subject := concat(PointNetString, '/', Subject);
  917.                     SendFileName := concat(GenericPath, 'Sendfiles', Subject, '.bbs');
  918.                     MakeTextFile(SendFileName);
  919.                     Err := FSOpen(SendFileName, vRefNum, SendFilesRef);
  920.                     Err := SetFPos(SendFilesRef, fsFromLEOF, 0);
  921.  
  922.                     MakeTextFile(concat(GenericPath, 'Generic Export'));
  923.                     Err := FSOpen(concat(GenericPath, 'Generic Export'), vRefNum, GenExpRef);
  924.                     Err := SetFPos(GenExpRef, fsFromLEOF, 0);
  925.  
  926.                     MakeTextFile(':Tabby:AreaTrix Workfile');
  927.                     Err := FSOpen(':Tabby:AreaTrix Workfile', vRefNum, AFWLogRef);
  928.                     Err := SetFPos(AFWLogRef, fsFromLEOF, 0);
  929.  
  930.                     if ListForwards then
  931.                         begin
  932.                             MakeTextFile(':Tabby:Forward Log');
  933.                             Err := FSOpen(':Tabby:Forward Log', vRefNum, ForwardLogRef);
  934.                             Err := SetFPos(ForwardLogRef, fsFromLEOF, 0)
  935.                         end;
  936.  
  937.                     WriteHeading(GenExpRef, ForwardName);
  938.                     TempString := concat('The following files were processed for forwarding to ', Subject, ':');
  939.                     Err := MyWriteLine(GenExpRef, TempString);
  940.                     TempString := '   ';
  941.                     Err := MyWriteLine(GenExpRef, TempString);
  942.                     Empty := true;
  943.                     for FilesToDo := 1 to Index do
  944.                         begin
  945.                             TempString := BlankStrip(MsgTextArray[FilesToDo]^^);
  946.                             if (TempString <> ' ') & (TempString <> TAB) & (TempString <> '') then
  947.                                 begin
  948.                                     TempString := concat(GenericPath, MsgTextArray[FilesToDo]^^);
  949.                                     Err := FSOpen(TempString, vRefNum, FileCheckRef);
  950.                                     if Err = NoErr then
  951.                                         begin
  952.                                             Empty := false;
  953.                                             Err := FSClose(FileCheckRef);
  954.                                             Err := MyWriteLine(SendFilesRef, TempString);
  955.                                             TempLogString := concat(MsgTextArray[FilesToDo]^^, TAB, 'Sendfiles', Subject, '.bbs');
  956.                                             Err := MyWriteLine(AFWLogRef, TempLogString);
  957.                                             TimeStamp;
  958.                                             if ListForwards then
  959.                                                 begin
  960.                                                     TempLogString := concat(TabbyStamp, ' -- ', MsgTextArray[FilesToDo]^^, ' sent from ', FromName, ' to ', Subject);
  961.                                                     Err := MyWriteLine(ForwardLogRef, TempLogString)
  962.                                                 end;
  963.                                             TempString := concat(MsgTextArray[FilesToDo]^^, ' -- file set up to be sent');
  964.                                             Err := MyWriteLine(GenExpRef, TempString)
  965.                                         end        {    if it opened OK    }
  966.                                     else if (length(MsgTextArray[FilesToDo]^^) > 1) then
  967.                                         begin
  968.                                             Empty := false;
  969.                                             TempString := concat(MsgTextArray[FilesToDo]^^, ' -- file not found');
  970.                                             Err := MyWriteLine(GenExpRef, TempString)
  971.                                         end
  972.                                 end            {    if it wasn't an empty line        }
  973.                         end;    {    for FilesToDo := 1 to Index        }
  974.  
  975.                     if Empty then
  976.                         begin
  977.                             TempString := 'No files found!';
  978.                             Err := MyWriteLine(GenExpRef, TempString)
  979.                         end;
  980.  
  981.                     Err := FSClose(AFWLogRef);
  982.                     if ListForwards then
  983.                         Err := FSClose(ForwardLogRef);
  984.                     Err := FSClose(SendFilesRef);
  985.                     WriteClosing(GenExpRef);
  986.                     Err := FSClose(GenExpRef);
  987.                 end        {    if GoodPassword    }
  988.         end;    {    if addressed to ForwardName    }
  989.  
  990. { ------------------------------------------------------ }
  991.  
  992.     procedure DoAreaFix;
  993.  
  994.         begin
  995.             InterpretRequest;
  996.             if Request = true then
  997.                 begin
  998.                     MessageCount := succ(MessageCount);
  999.                     CheckPoint;
  1000.                     if GoodPassword then
  1001.                         AlterAreas;
  1002.                     SendMsg('AreaFix');
  1003.                 end            {    If Request = true    }
  1004.         end;            {    if (CapsToName = 'AREAFIX') | (CapsToName = 'AREATRIX')'    }
  1005.  
  1006. { ------------------------------------------------------ }
  1007.  
  1008.     procedure DoFREQ;
  1009.  
  1010.         const
  1011.             LF = chr(10);
  1012.  
  1013.         var
  1014.             Counter, FilesToDo, FQRef: integer;
  1015.             NodeInHex, RequestName, BBSRezName, FileToGet, TempLaunchString: str255;
  1016.             CharsToRead: longint;
  1017.             AlreadyThere: boolean;
  1018.  
  1019.         begin
  1020.             InterpretRequest;        {    Just want to make sure we've got a good password    }
  1021.             if GoodPassword & (pos('>', Subject) > 0) then
  1022.                 begin
  1023.                     BBSRezName := GetString(500)^^;
  1024.                     Subject := BlankStrip(Subject);
  1025.                     Subject := copy(Subject, pos('>', Subject) + 1, 255);
  1026.                     Subject := BlankStrip(Subject);
  1027.                     TempString := '';
  1028.                     for Counter := 1 to length(Subject) do
  1029.                         if Subject[Counter] in ['0'..'9', '/'] then
  1030.                             TempString := concat(TempString, Subject[Counter]);
  1031.                     Subject := TempString;
  1032.                     if Subject <> '' then
  1033.                         begin
  1034.                             MakeTextFile('Fakebot Script');
  1035.                             Err := FSOpen('Fakebot Script', vRefNum, FQRef);
  1036.                             if Err = NoErr then
  1037.                                 Err := GetEOF(FQRef, logicalEOF);
  1038.                             if (Err = NoErr) & (LogicalEOF > 1) then
  1039.                                 begin
  1040.                                     Err := SetFPos(FQRef, fsFromLEOF, -1);
  1041.                                     CharsToSend := 1;
  1042.                                     TempString := SPACE;
  1043.                                     if Err = NoErr then
  1044.                                         Err := MyWrite(FQRef, TempString);
  1045.                                 end;
  1046.                             if Err = NoErr then
  1047.                                 Err := SetFPos(FQRef, fsFromLEOF, 0);
  1048.                             CharsToSend := length(Subject);
  1049.                             if Err = NoErr then
  1050.                                 Err := MyWriteLine(FQRef, Subject);
  1051.                             Err := FSClose(FQRef);        {    'Fakebot Script'    }
  1052.  
  1053.                             TempLaunchString := '';
  1054.                             MakeTextFile('launch.next');
  1055.                             Err := FSOpen('launch.next', vRefNum, FQRef);
  1056.                             if Err = NoErr then
  1057.                                 Err := GetEOF(FQRef, logicalEOF);
  1058.                             if Err = NoErr then
  1059.                                 if (LogicalEOF < 255) then
  1060.                                     begin
  1061.                                         Err := ReadALine(FQRef, TempLaunchString);
  1062.                                         Err := SetFPos(FQRef, fsFromStart, 0)
  1063.                                     end
  1064.                                 else
  1065.                                     begin
  1066.                                         CharsToRead := 255;
  1067.                                         Err := SetFPos(FQRef, fsFromLEOF, -255);
  1068.                                         Err := FSRead(FQRef, CharsToRead, @TempLaunchString);
  1069.                                         TempLaunchString := copy(TempLaunchString, 1, length(TempLaunchString) - 1);    {trim CR}
  1070.                                         Err := SetFPos(FQRef, fsFromLEOF, -255)
  1071.                                     end;
  1072.                             if (Err = NoErr) then
  1073.                                 if pos(BBSRezName, TempLaunchString) > 0 then
  1074.                                     TempLaunchString := copy(TempLaunchString, 1, pos(BBSRezName, TempLaunchString) - 1);
  1075.                             while (TempLaunchString[length(TempLaunchString)] in [',', SPACE]) do
  1076.                                 TempLaunchString := copy(TempLaunchString, 1, length(TempLaunchString) - 1);
  1077.                             TempLaunchString := concat(TempLaunchString, ',', FREQName, ENDLINE);
  1078.                             if Err = NoErr then
  1079.                                 Err := MyWrite(FQRef, TempLaunchString);
  1080.                             if LogicalEOF < 255 then
  1081.                                 Err := SetEOF(FQRef, length(TempLaunchString))
  1082.                             else
  1083.                                 Err := SetEOF(FQRef, logicalEOF + length(TempLaunchString) - 255);
  1084.                             Err := FSClose(FQRef);        {    'launch.next'    }
  1085.  
  1086.                             NodeInHex := HexNode(Subject);
  1087.                             RequestName := concat(':Tabby:', NodeInHex, '.REQ');
  1088.                             MakeTextFile(RequestName);
  1089.                             Err := FSOpen(RequestName, vRefNum, FQRef);
  1090.                             if Err = NoErr then
  1091.                                 Err := SetFPos(FQRef, fsFromLEOF, 0);
  1092.  
  1093.                             if Err = NoErr then
  1094.                                 for FilesToDo := 1 to Index do
  1095.                                     begin
  1096.                                         FileToGet := BlankStrip(MsgTextArray[FilesToDo]^^);
  1097.                                         if (FileToGet[1] = '-') & (FileToGet[2] = '-') & (FileToGet[3] = '-') then
  1098.                                             leave
  1099.                                         else if (FileToGet <> ' ') & (FileToGet <> TAB) & (FileToGet <> '') then
  1100.                                             begin
  1101.                                                 Err := MyWriteLine(FQRef, FileToGet);
  1102.                                                 TempString := LF;
  1103.                                                 Err := MyWrite(FQRef, TempString);        {write linefeed after CR}
  1104.                                             end;            {    if (TempString <> ' ') & (TempString <> TAB) & (TempString <> '')    }
  1105.                                     end;        {    for FilesToDo := 1 to Index    }
  1106.                             Err := FSClose(FQRef);        {    ':Tabby:', NodeInHex, '.REQ'    }
  1107.  
  1108.                             AlreadyThere := false;
  1109.                             SendFileName := concat(GenericPath, 'Sendfiles', Subject, '.bbs');
  1110.                             MakeTextFile(SendFileName);
  1111.                             Err := FSOpen(SendFileName, vRefNum, FQRef);
  1112.                             while not AtEOF(FQRef) do
  1113.                                 begin
  1114.                                     Err := ReadALine(FQRef, TempString);
  1115.                                     if Tempstring = RequestName then
  1116.                                         AlreadyThere := true
  1117.                                 end;
  1118.                             if not AlreadyThere then
  1119.                                 begin
  1120.                                     if Err = NoErr then
  1121.                                         Err := SetFPos(FQRef, fsFromLEOF, 0);
  1122.                                     if Err = NoErr then
  1123.                                         Err := MyWriteLine(FQRef, RequestName);
  1124.                                 end;        {    if not AlreadyThere    }
  1125.                             Err := FSClose(FQRef);        {    'Sendfiles', Subject, '.bbs'    }
  1126.  
  1127.                         end        {    if Subject <> ''                        }
  1128.                 end        {    if GoodPassword & (pos('>', Subject) > 0)    }
  1129.         end;    {    procedure DoFREQ    }
  1130.  
  1131. { ------------------------------------------------------ }
  1132.  
  1133.     begin
  1134.         Request := false;
  1135.         Err := FSOpen(':Tabby:Tabby Config', vRefNum, TConfigRef);
  1136.         if Err = NoErr then
  1137.             begin
  1138.                 Err := ReadALine(TConfigRef, LocalNodeID);
  1139.                 Err := FSClose(TConfigRef);
  1140.                 Colon := pos(':', LocalNodeID);
  1141.                 LocalNodeID := copy(LocalNodeID, Colon + 1, length(LocalNodeID) - Colon);
  1142.                 ReadAreas;            {    Read Areas.bbs file and store info        }
  1143.                 ReadPointFeeds;    {    Read PointGroups file and store info    }
  1144.                 Err := FSOpen('AreaTrix.req', vRefNum, AreafixRef);
  1145.                 if Err = NoErr then
  1146.                     Err := GetEOF(AreafixRef, AreaFixEOF);
  1147.                 if (Err = NoErr) and (AreaFixEOF > 0) then
  1148.                     begin
  1149.                         Err := GetFPos(AreafixRef, FlagPos);
  1150.                         while (FlagPos < AreaFixEOF) do
  1151.                             begin
  1152.                                 Err := ReadALine(AreafixRef, FlagLine);
  1153.                                 if FlagLine[1] <> 'D' then
  1154.                                     begin
  1155.                                         Err := SetFPos(AreafixRef, fsFromStart, FlagPos);
  1156.                                         FlagLine[1] := 'D';
  1157.                                         Err := MyWriteLine(AreafixRef, FlagLine);
  1158.                                         Err := ReadALine(AreafixRef, Ignore);    {    Sect    }
  1159.                                         Err := ReadALine(AreafixRef, Ignore);    {    Date    }
  1160.                                         Err := ReadALine(AreafixRef, Ignore);    {    Time    }
  1161.                                         Err := ReadALine(AreafixRef, NodeID);
  1162.                                         Err := ReadALine(AreafixRef, FromName);
  1163.                                         Err := ReadALine(AreafixRef, ToName);
  1164.                                         CapsToName := ToName;
  1165.                                         UprString(CapsToName, false);
  1166.                                         Err := ReadALine(AreafixRef, Subject);
  1167.                                         Index := 1;
  1168.                                         TextLine := '';
  1169.                                         while (not AtEOF(AreafixRef)) & (pos(NULL, TextLine) = 0) & (Index < 401) do
  1170.                                             begin
  1171.                                                 Err := ReadALine(AreafixRef, TextLine);
  1172.                                                 if (pos(NULL, TextLine) = 0) & (Err = NoErr) then
  1173.                                                     begin
  1174.                                                         MsgTextArray[Index] := MsgTextHndl(NewHandle(sizeOf(MsgTextLine)));
  1175.                                                         HLock(Handle(MsgTextArray[Index]));
  1176.                                                         MsgTextArray[Index]^^ := TextLine;
  1177.                                                         Index := succ(Index)
  1178.                                                     end
  1179.                                             end;
  1180.                                         Index := pred(Index);
  1181.  
  1182.                                         if CapsToName = CapsFwdName then
  1183.                                             DoFileForward
  1184.  
  1185.                                         else if (CapsToName = 'AREAFIX') | (CapsToName = 'AREATRIX') then
  1186.                                             DoAreaFix
  1187.  
  1188.                                         else if CapsToName = CapsFREQName then
  1189.                                             DoFREQ
  1190.  
  1191.                                         else if CapsToName = CapsAgentName then
  1192.                                             begin
  1193.                                                 InterpretRequest;        {    Just want to make sure we've got a good password    }
  1194.                                                 if GoodPassword then
  1195.                                                     begin
  1196.  
  1197.                                                     end
  1198.                                             end;
  1199.  
  1200.                                         for Counter := 1 to Index do
  1201.                                             begin
  1202.                                                 HUnlock(Handle(MsgTextArray[Counter]));
  1203.                                                 DisposHandle(Handle(MsgTextArray[Counter]))
  1204.                                             end
  1205.  
  1206.                                     end        {    if FlagLine[1] <> 'D'        }
  1207.                                 else
  1208.                                     begin            {    FlagLine[1] = 'D'        }
  1209.                                         TextLine := '';
  1210.                                         while (pos(chr(0), TextLine) = 0) & (FlagPos < AreaFixEOF) do
  1211.                                             begin
  1212.                                                 Err := ReadALine(AreafixRef, TextLine);
  1213.                                                 Err := GetFPos(AreafixRef, FlagPos)
  1214.                                             end
  1215.                                     end;        {    if FlagLine[1] = 'D'        }
  1216.                                 Err := GetFPos(AreafixRef, FlagPos)
  1217.                             end        {    while (FlagPos < AreaFixEOF)        }
  1218.                     end;    {    if (Err = NoErr) and (AreaFixEOF > 0)    }
  1219.                 Err := FSClose(AreafixRef);
  1220.  
  1221.                 UpdateAreaFile(':Tabby:areas.bbs', AreaArray, AreaIndex);
  1222.                 UpdateAreaFile(':Tabby:PointGroups', PointFeedArray, PointIndex);
  1223.  
  1224.                 for Counter := 1 to AreaIndex do
  1225.                     begin
  1226.                         HUnlock(Handle(AreaArray[Counter]));
  1227.                         DisposHandle(Handle(AreaArray[Counter]))
  1228.                     end;
  1229.                 for Counter := 1 to PointIndex do
  1230.                     begin
  1231.                         HUnlock(Handle(PointFeedArray[Counter]));
  1232.                         DisposHandle(Handle(PointFeedArray[Counter]))
  1233.                     end
  1234.  
  1235.             end        {    if Err = NoErr for Config file    }
  1236.     end;
  1237.  
  1238. { ------------------------------------------------------ }
  1239.  
  1240. procedure Initialize;
  1241.  
  1242.     type
  1243.  
  1244.         NumVersion = packed record
  1245.                 case INTEGER of
  1246.                     0: (
  1247.                             majorRev: SignedByte;        {1st part of version number in BCD        }
  1248.                             minorRev: 0..9;            {2nd part is 1 nibble in BCD}
  1249.                             bugFixRev: 0..9;            {3rd part is 1 nibble in BCD}
  1250.                             stage: SignedByte;        {stage code: dev, alpha, beta, final}
  1251.                             nonRelRev: SignedByte
  1252.                     ); {revision level of non-released version}
  1253.  
  1254.                     1: (
  1255.                             version: LONGINT
  1256.                     );     {to use all 4 fields at one time}
  1257.             end;
  1258.  
  1259.         VersRec = record
  1260.                 numericVersion: NumVersion;        {encoded version number}
  1261.                 countryCode: INTEGER;            {country code from intl utilities}
  1262.                 shortVersion: STR255;            {version number string - worst case}
  1263.                 reserved: STR255;                {longMessage string packed after shortVersion    }
  1264.             end;
  1265.  
  1266.         VersRecPtr = ^VersRec;
  1267.         VersRecHndl = ^VersRecPtr;
  1268.  
  1269.     var
  1270.         versionHndl: VersRecHndl;
  1271.  
  1272.     begin
  1273.         CurrentResFile := CurResFile;
  1274.         versionHndl := VersRecHndl(NewHandle(sizeOf(VersRec)));
  1275.         versionHndl := VersRecHndl(GetResource('vers', 1));
  1276.         NumToString(versionHndl^^.numericVersion.majorRev, TheVers);
  1277.         NumToString(versionHndl^^.numericVersion.minorRev, TempString);
  1278.         TheVers := concat(TheVers, '.', TempString);
  1279.         if (versionHndl^^.numericVersion.bugFixRev > 0) then
  1280.             begin
  1281.                 NumToString(versionHndl^^.numericVersion.bugFixRev, TempString);
  1282.                 TheVers := concat(TheVers, TempString)
  1283.             end;
  1284.         DisposHandle(Handle(versionHndl));
  1285.         OptionStr := GetString(501)^^;
  1286.         uprString(OptionStr, false);
  1287.         if OptionStr[1] = 'Y' then
  1288.             MsgToSysop := true
  1289.         else
  1290.             MsgToSysop := false;
  1291.         if OptionStr[2] = 'Y' then
  1292.             ListOK := true
  1293.         else
  1294.             ListOK := false;
  1295.         if OptionStr[3] = 'Y' then
  1296.             TabbyLog := true
  1297.         else
  1298.             TabbyLog := false;
  1299.         if OptionStr[4] = 'Y' then
  1300.             ListForwards := true
  1301.         else
  1302.             ListForwards := false;
  1303.         if OptionStr[5] = 'Y' then
  1304.             DeleteForwards := true
  1305.         else
  1306.             DeleteForwards := false;
  1307.         if OptionStr[6] = 'Y' then
  1308.             ListFREQs := true
  1309.         else
  1310.             ListFREQs := false;
  1311.         ForwardName := GetString(502)^^;
  1312.         CapsFwdName := ForwardName;
  1313.         uprString(CapsFwdName, false);
  1314.         FREQName := GetString(503)^^;
  1315.         CapsFREQName := FREQName;
  1316.         uprString(CapsFREQName, false);
  1317.         AgentName := GetString(504)^^;
  1318.         CapsAgentName := AgentName;
  1319.         uprString(CapsAgentName, false)
  1320.     end;
  1321.  
  1322. { ------------------------------------------------------ }
  1323.  
  1324. procedure WriteLogStart;
  1325.  
  1326.     begin
  1327.         TimeStamp;
  1328.         MakeTextFile(':Tabby:Tabby Log');
  1329.         Err := FSOpen(':Tabby:Tabby Log', vRefNum, TLogRef);
  1330.         Err := SetFPos(TLogRef, fsFromLEOF, 0);
  1331.         TempString := concat(TabbyStamp, 'AreaTrix  - Program Starting');
  1332.         Err := MyWriteLine(TLogRef, TempString);
  1333.         Err := FSClose(TLogRef)
  1334.     end;
  1335.  
  1336. { ------------------------------------------------------ }
  1337.  
  1338. procedure WriteLogEnd;
  1339.  
  1340.     begin
  1341.         TimeStamp;
  1342.         Err := FSOpen(':Tabby:Tabby Log', vRefNum, TLogRef);
  1343.         Err := SetFPos(TLogRef, fsFromLEOF, 0);
  1344.         NumToString(MessageCount, TempString);
  1345.         TempString := concat('AreaTrix  - ', TempString, ' request');
  1346.         if MessageCount <> 1 then
  1347.             TempString := concat(TempString, 's');
  1348.         TempString := concat(TempString, ' processed');
  1349.         TempString := concat(TabbyStamp, TempString);
  1350.         Err := MyWriteLine(TLogRef, TempString);
  1351.         TempString := concat(TabbyStamp, 'AreaTrix  - Program Ending');
  1352.         Err := MyWriteLine(TLogRef, TempString);
  1353.         Err := FSClose(TLogRef)
  1354.     end;
  1355.  
  1356. { ------------------------------------------------------ }
  1357.  
  1358. function ReadShortFile (FileName: STR255): STR255;
  1359.  
  1360.     var
  1361.         fileRef: integer;
  1362.         endOfFile: longint;
  1363.         OneLine: STR255;
  1364.  
  1365.     begin
  1366.         Err := FSOpen(FileName, vRefNum, fileRef);
  1367.         if (Err = NoErr) then
  1368.             Err := GetEOF(fileRef, endOfFile);
  1369.         if (endOfFile > 0) & (Err = NoErr) then
  1370.             Err := ReadALine(fileRef, OneLine)
  1371.         else
  1372.             OneLine := '';
  1373.         if (Err = NoErr) then
  1374.             Err := FSClose(fileRef);
  1375.         ReadShortFile := OneLine
  1376.     end;
  1377.  
  1378. { ------------------------------------------------------ }
  1379.  
  1380. begin
  1381.     Initialize;
  1382.     if Button then
  1383.         HandleDialog(TheVers)        { If user is holding down the mouse button, reconfigure and end }
  1384.     else
  1385.         begin
  1386.             DialogPointer := GetNewDialog(1001, nil, POINTER(-1));
  1387.             DrawDialog(DialogPointer);
  1388.             SetPort(DialogPointer);
  1389.  
  1390.             if TabbyLog then
  1391.                 WriteLogStart;
  1392.  
  1393.             HelloTabby;    { find out what's next on the launchpad }
  1394.             GenericPath := ReadShortFile(':Generic');
  1395.             PurgeFiles(GenericPath);
  1396.             PointNetString := ReadShortFile(':Tabby:Point Net');
  1397.             MessageCount := 0;
  1398.             PreScan(GenericPath, CapsFwdName, CapsFREQName, FixPending);
  1399.             if FixPending then
  1400.                 begin
  1401.                     ParseReq;
  1402.                     Err := FSDelete('AreaTrix.req', vRefNum)
  1403.                 end;        {    if FixPending    }
  1404.  
  1405.             if TabbyLog then
  1406.                 WriteLogEnd;
  1407.  
  1408.             DisposDialog(DialogPointer)
  1409.  
  1410.         end;        {    not holding down button    }
  1411.  
  1412.     if NextLaunch <> '' then
  1413.         LaunchNextAppl
  1414.  
  1415. end.        {    of main routine    }